package tse

import (
	"gitee.com/amoyx/cloud-provider/pkg/cloud/tencent/models"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
	qtse "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tse/v20201207"
)

type ApolloGreeter interface {
	Apollo(region string) ApolloInterface
}

type ApolloInterface interface {
	CreateInstance(args models.ApolloRequest) (result models.CreateResponseParams, err error)
	Get(id string) (result models.ApolloResponse, err error)
	ListByName(name string) (list []models.ApolloResponse, err error)
	ListAll() (list []models.ApolloResponse, err error)
	DeleteInstance(id string) (err error)
	EnableWanAddr(id string) (err error)
	DisableWanAddr(id string) (err error)
	QueryInstanceAccessAddress(id string) (result models.InstanceAccessAddress, err error)
}

type apollo struct {
	tse    *TSE
	region string
	client *qtse.Client
}

func newApollo(tse *TSE, region string) ApolloInterface {
	v := &apollo{
		tse:    tse,
		region: region,
	}
	cpf := profile.NewClientProfile()
	cpf.HttpProfile.Endpoint = string(TseEndPoint)
	client, _ := qtse.NewClient(v.tse.Credential(), v.region, cpf)
	v.client = client
	return v
}

// CreateInstance 创建apollo实例
func (a *apollo) CreateInstance(args models.ApolloRequest) (result models.CreateResponseParams, err error) {
	request := qtse.NewCreateEngineRequest()
	request.EngineType = common.StringPtr("apollo")
	request.EngineVersion = common.StringPtr(args.EngineVersion)
	request.EngineProductVersion = common.StringPtr("STANDARD")
	request.EngineRegion = common.StringPtr(a.region)
	request.EngineName = common.StringPtr(args.EngineName)
	var envs []*qtse.ApolloEnvParam
	for _, e := range args.EnvInfos {
		tempEnv := qtse.ApolloEnvParam{
			Name:               common.StringPtr(e.Name),
			EngineResourceSpec: common.StringPtr(e.EngineResourceSpec),
			EngineNodeNum:      common.Int64Ptr(e.EngineNodeNum),
			StorageCapacity:    common.Int64Ptr(e.StorageCapacity),
			VpcId:              common.StringPtr(e.VpcId),
			SubnetId:           common.StringPtr(e.SubnetId),
			EnvDesc:            common.StringPtr(e.EnvDesc),
		}
		envs = append(envs, &tempEnv)
	}
	request.ApolloEnvParams = envs
	request.EngineAdmin = &qtse.EngineAdmin{
		Name:     common.StringPtr(args.EngineAdmin.Name),
		Password: common.StringPtr(args.EngineAdmin.Password),
		Token:    common.StringPtr(args.EngineAdmin.Token),
	}
	request.TradeType = common.Int64Ptr(0)
	request.PrepaidPeriod = common.Int64Ptr(1)
	request.PrepaidRenewFlag = common.Int64Ptr(1)
	response, err := a.client.CreateEngine(request)
	if err != nil {
		return
	}
	res := response.Response
	result.RequestId = *res.RequestId
	result.InstanceSet = append(result.InstanceSet, *res.InstanceId)
	return
}

func (a *apollo) Get(id string) (result models.ApolloResponse, err error) {
	list, err := a.query(map[string]string{"InstanceId": id})
	if len(list) > 0 {
		result = list[0]
	}
	return
}

// DeleteInstance 删除apollo实例
func (a *apollo) DeleteInstance(id string) (err error) {
	request := qtse.NewDeleteEngineRequest()
	request.InstanceId = common.StringPtr(id)
	_, err = a.client.DeleteEngine(request)
	return
}

func (a *apollo) ListByName(name string) (list []models.ApolloResponse, err error) {
	return a.query(map[string]string{"Name": name})
}

func (a *apollo) ListAll() (list []models.ApolloResponse, err error) {
	return a.query(map[string]string{})
}

// EnableWanAddr 开启公网访问
func (a *apollo) EnableWanAddr(id string) (err error) {
	request := qtse.NewUpdateEngineInternetAccessRequest()
	request.InstanceId = common.StringPtr(id)
	request.EnableClientInternetAccess = common.BoolPtr(true)
	request.EngineType = common.StringPtr("apollo")
	_, err = a.client.UpdateEngineInternetAccess(request)
	return
}

// DisableWanAddr 关闭公网访问
func (a *apollo) DisableWanAddr(id string) (err error) {
	request := qtse.NewUpdateEngineInternetAccessRequest()
	request.InstanceId = common.StringPtr(id)
	request.EnableClientInternetAccess = common.BoolPtr(false)
	request.EngineType = common.StringPtr("apollo")
	_, err = a.client.UpdateEngineInternetAccess(request)
	return
}

func (a *apollo) QueryInstanceAccessAddress(id string) (result models.InstanceAccessAddress, err error) {
	request := qtse.NewDescribeSREInstanceAccessAddressRequest()
	request.InstanceId = common.StringPtr(id)
	response, err := a.client.DescribeSREInstanceAccessAddress(request)
	if err != nil {
		return
	}
	res := response.Response
	result.ConsoleInternetAddress = *res.ConsoleInternetAddress
	result.ConsoleIntranetAddress = *res.ConsoleIntranetAddress
	result.IntranetAddress = *res.IntranetAddress
	result.InternetAddress = *res.InternetAddress
	result.RequestId = *res.RequestId
	return
}

func (a *apollo) query(args map[string]string) (list []models.ApolloResponse, err error) {
	request := qtse.NewDescribeSREInstancesRequest()
	var filters []*qtse.Filter
	for key, val := range args {
		filters = append(filters, &qtse.Filter{
			Name:   common.StringPtr(key),
			Values: common.StringPtrs([]string{val}),
		})
	}
	request.Limit = common.Int64Ptr(1000)
	request.Offset = common.Int64Ptr(0)
	request.QueryType = common.StringPtr("apollo")
	response, err := a.client.DescribeSREInstances(request)
	if err != nil {
		return
	}
	for _, row := range response.Response.Content {
		var envs []models.ApolloEnvInfo
		for _, env := range row.EnvInfos {
			var vpcs []models.VpcInfo
			for _, vpc := range env.VpcInfos {
				vpcs = append(vpcs, models.VpcInfo{
					VpcId:           *vpc.VpcId,
					SubnetId:        *vpc.SubnetId,
					IntranetAddress: *vpc.IntranetAddress,
				})
			}
			envs = append(envs, models.ApolloEnvInfo{
				EnvName:                 *env.EnvName,
				VpcInfos:                vpcs,
				StorageCapacity:         *env.StorageCapacity,
				Status:                  *env.Status,
				AdminServiceIp:          *env.AdminServiceIp,
				ConfigServiceIp:         *env.ConfigServiceIp,
				EnableConfigInternet:    *env.EnableConfigInternet,
				ConfigInternetServiceIp: *env.ConfigInternetServiceIp,
				SpecId:                  *env.SpecId,
				EnvReplica:              *env.EnvReplica,
				RunningCount:            *env.RunningCount,
				EnvDesc:                 *env.EnvDesc,
				ClientBandWidth:         *env.ClientBandWidth,
				EnableConfigIntranet:    *env.EnableConfigIntranet,
			})
		}
		addrInfo, _ := a.QueryInstanceAccessAddress(*row.InstanceId)
		content := models.ApolloResponse{
			EnvInfos: envs,
			TseBaseResponse: models.TseBaseResponse{
				InstanceId:            *row.InstanceId,
				Name:                  *row.Name,
				EngineVesion:          *row.Edition,
				Status:                *row.Status,
				SpecId:                *row.SpecId,
				Replica:               *row.Replica,
				EngineType:            *row.Type,
				VpcId:                 *row.VpcId,
				Paymode:               *row.Paymode,
				CreateTime:            *row.CreateTime,
				EngineRegion:          *row.EngineRegion,
				EnableInternet:        *row.EnableInternet,
				EnableConsoleInternet: *row.EnableConsoleInternet,
				EnableConsoleIntranet: *row.EnableConsoleIntranet,
				ConfigInfoVisible:     *row.ConfigInfoVisible,
				ConsoleDefaultPwd:     *row.ConsoleDefaultPwd,
				TradeType:             *row.TradeType,
				AutoRenewFlag:         *row.AutoRenewFlag,
				CurDeadline:           *row.CurDeadline,
				IsolateTime:           *row.IsolateTime,
				ProductVersion:        *row.FeatureVersion,
				EnableClientIntranet:  *row.EnableClientIntranet,
				InstanceAccessAddress: addrInfo,
			},
		}
		list = append(list, content)
	}
	return
}
